<?php

/** soList class.
 *
 *  This collection of functions (libary) is licensed under GPL2.
 *  See LICENSE or www.gnu.org for more details.
 *  @author Jyry Kuukkanen
 *  @copyright Jyry Kuukkanen
*/


include_once("sobaseclass.php");
include_once("sogeneric.php");


/** This class is a flexible way to store any type of variables or objects
 *      into a list, remove items, compare to another etc. Basicly this is
 *      just array that is accessed in an controlled manner using methods.
 *  @author Jyry Kuukkanen
 *  @var array/any $Items Stored items
 *  @package solist
 */
class soList extends soBaseClass {

    /* @access private */
    var $Items;

    /* constructor */
    function soList() {
        $this->soBaseClass();
        $this->Items = array();
    } // constructor

  
    /** getItem($Pos)
     *  Returns an item at $Pos.
     *  On error set $this->Error to true (1).
     *  @package solist
     */
    function getItem($Pos) {
        if (($Pos < 0) || ($Pos >= $this->count())) {
            $this->Error = 1;
            return ""; // <-- EXIT
        };

        $this->Error = 0;
        return $this->Items[$Pos];
    } // getItem


    /** Stores an item to list.
     *  Stores the specified item at specified position in the list.
     *  @param any $Value Value to store.
     *  @param int $Pos Position in the list to store.
     *  @return bool Returns true(1) if position was within range, or false(0)
     *       if not (Error property is set to true, too).
     *  @package solist
     */
    function setItem($Value, $Pos) {
        if (($Pos < 0) || ($Pos >= $this->count())) {
            $this->Error = 1;
            return 0; // <-- EXIT
        };
        $this->Items[$Pos] = $Value;
        $this->Error = 0;
        return 1;
    } // setItem


    /** Inserts an item to the list.
     *  Inserts an item before item at specified position, or to the end 
     *  (-1, default).
     *  @param any $Item Item to insert
     *  @param int $Pos Position in the list
     *  @return bool True(1) on success, otherwise 0 ($Pos > itemcount or < -1)
     *       and $this->Error is set to true(1);
     *  @package solist
     */
    function insItem($Item, $Pos = -1) {
        return soInsElement($this->Items, $Item, $Pos);
    } // insItem


    /** Deletes an item from the list.
     *  Deletes an item at specified location in the list.
     *  @param int $Pos Position in the list
     *  @return bool True(1) on success, otherwise 0 ($Pos > itemcount) or
     *      ($Pos < 0). $this->Error is also set to true (1) on error;
     *  @package solist
     */
    function delItem($Pos) {
        return soDelElement($this->Items, $Pos);
    } // delItem


    /** Removes the last element from the list.
     *  @return any Returns the last element on success or false(0) if list is empty.
     *  @package solist
     */
    function popItem() {
        $icount = count($this->Items);
        if ($icount == 0) return 0;
        $result = getItem($icount -1);
        $this->delItem($icount -1);

        return $result;
    } // popItem
    

    /** Deletes all items from the list.
     *  @package solist
     */
    function clearList() {
        $this->Items = array();
    } // clearList


    /** Compare an item list to a value.
     *  @param int $Pos Position in the list
     *  @param any $CompItem A value to compare the item at $Pos to.
     *  @return int Results one of the following:
     *    0 Items at $Pos and $CompItem are equal
     *    1 Items are of different type (boolean, inteter, object, etc.)
     *    2 Items are of type object, but different class type
     *    3 Items are not equal
     *  @package solist
     */
    function compItem($Pos, $CompItem) {
        $type = gettype($this->Items[$Pos]);
        $comp_type = gettype($CompItem);
        if ($type != $comp_type) return 1; // <-- EXIT

        if (($type == "object") &&
             (soGetClass($CompItem) != soGetClass($this->Items[$Pos]))) {
            return 2; // <--EXIT
        }; // if type=object

        if ($this->Items[$Pos] == $CompItem) {
            return 0; // <-- EXIT
        } else {
            return 3; // <--EXIT
        };
    } // compItem

  
    /** Returns the number of items in the list.
     *  @package solist
     */
    function count() {
        return count($this->Items);
    } // count


    /** Swaps places of two items in the list.
     *  Swaps places of items at postiion $A_pos and $B_pos in the list.
     *  @param int $A_pos Position of item A in the list
     *  @param int $B_pos Position of item B in the list
     *  @return bool True(1) when $A_pos and $B_pos are in range, otherwise
     *      false(0).
     *  @package solist
     */
    function swapItems($A_pos, $B_pos) {
        $lcount = $this->count();
        if (($A_pos < 0) || ($B_pos < 0) ||
            ($A_pos >= $lcount) || ($B_pos >= $lcount)) return 0; // <-- EXIT

        $tmp = $this->Items[$A_pos];
        $this->Items[$B_pos] = $this->Items[$A_pos];
        $this->Items[$A_pos] = $tmp;

        return 1;
    } // swapItems


    /** Moves an item from one pos to another.
     *  Moves the item at position to new position. Others items are moved
     *  acordingly forward or backward. This is a bit strange method and should
     *  probably not be used at all to keep the code understandable.
     *  @param int $FromPos Position to move (copy+del) an item from.
     *  @param int $ToPos Position to move the item to.
     *  @return bool True(1) when $FromPos and $ToPos are in range, otherwise
     *      false(0).
     *  @package solist
     */
    function  moveItem($FromPos, $ToPos) {
        /* Check whether positions are both valid */
        if (($FromPos < -1) || ($FromPos >= $this->count()) ||
            ($ToPos < -1) || ($ToPos >= $this->count()) ||
            ($FromPos == $ToPos)) {
            $this->Error = 1;
            return 0; // <-- EXIT
        };

		$tmp = $this->getItem($FromPos);
		$this->delItem($FromPos);
		if ($FromPos < $ToPos) $ToPos--;
		$this->insItem($tmp, $ToPos);

        return 1;
    } //  moveItem


    /** Find an item in the list.
     *  Finds an item with given value and returns it's position.
     *  If $Occurance is specified, then $Occurance'th $Value is searched.
     *  @param any $Value Value to search for.
     *  @param $Occurance No. of occurance to search
     *  @return int List position or -1 if value was not found.
     *  @package solist
     */
    function findItem($Value, $Occurance = 1) {
        return soArrayFind($this->Items, $Value, $Occurance);
    } // findItem


    /** Returns the list as an array.
     *  Returns list elements from $Start postition to $End as an array.
     *  @param int $StartPos First item pos to return items from
     *  @param int $EndPos Last item pos to return items from
     *  @return array/any All or selected items from the list.
     *  @package solist
     */
    function toArray($StartPos = -1, $EndPos = -1) {
        $result = array();
        if ($this->count() == 0) return $result; // <-- EXIT

        if ($StartPos == -1) $Start = 0;
        if ($EndPos == -1) $EndPos = $this->count() -1;
        for ($i = $StartPos; $i <= $EndPos; $i++) {
            $result[] = $this->Items[$i];
        }; // for $i

        return $result;
    } // toArray


    /** Returns the list as string.
     *  Returns the specified range or all of list.
     *  @param string $Delim String to delimit elements from others.
     *  @param int $StartPos Starting element no. Use -1 to start from the
     *      begining.
     *  @param int $EndPos Ending element no. Use -1 to stop at he last element
     *  @return string List of elements as a string.
     *  @package solist
     */
    function toString($Delim, $StartPos = -1, $EndPos = -1) {
        $result = $this->toArray($StartPos, $EndPos);
        return implode($Delim, $result);
    } // toString

}; // soList

?>
